#include "vector3.h"

#include <cmath>
#include <cstdio>
#include <cstdlib>

namespace raytrace {

// static
const Vector3 Vector3::origin(0.0f, 0.0f, 0.0f);

// static
float Vector3::dot(Vector3Arg a, Vector3Arg b) {
  return a.x_ * b.x_ + a.y_ * b.y_ + a.z_ * b.z_;
}

// static
Vector3 Vector3::cross(Vector3Arg a, Vector3Arg b) {
  return Vector3(a.y_ * b.z_ - a.z_ * b.y_,
                 a.z_ * b.x_ - a.x_ * b.z_,
                 a.x_ * b.y_ - a.y_ * b.x_);
}

// static
Vector3 Vector3::add(Vector3Arg a, Vector3Arg b) {
  return Vector3(a.x_ + b.x_, a.y_ + b.y_, a.z_ + b.z_);
}

// static 
Vector3 Vector3::sub(Vector3Arg a, Vector3Arg b) {
  return Vector3(a.x_ - b.x_, a.y_ - b.y_, a.z_ - b.z_);
}

// static 
Vector3 Vector3::mul(Vector3Arg a, Vector3Arg b) {
  return Vector3(a.x_ * b.x_, a.y_ * b.y_, a.z_ * b.z_);
}

// static
Vector3 Vector3::div(Vector3Arg a, Vector3Arg b) {
  return Vector3(a.x_ / b.x_, a.y_ / b.y_, a.z_ / b.z_);
}

// static
Vector3 Vector3::scale(Vector3Arg a, float s) {
  return Vector3(a.x_ * s, a.y_ * s, a.z_ * s);
}

// static
Vector3 Vector3::scale(float s, Vector3Arg a) {
  return scale(a, s);
}

Vector3::Vector3()
  : x_(0.0f), y_(0.0f), z_(0.0f) {
}

Vector3::Vector3(Vector3Arg v)
  : x_(v.x_), y_(v.y_), z_(v.z_) {
}

Vector3::Vector3(float x, float y, float z)
  : x_(x), y_(y), z_(z) {
}

void Vector3::normalize() {
  const float len = sqrtf(length_sqr());
  if (len > 0)
    *this = scale(*this, 1.0f / len);
}

float Vector3::length_sqr() const {
  return x_ * x_ + y_ * y_ + z_ * z_;
}

}
